
/**
 * 字符串重新排序
 * 
 * 题目描述

给定一个字符串 s，s 包括以空格分隔的若干个单词，请对 s 进行如下处理后输出：

单词内部调整：对每个单词字母重新按字典序排序
单词间顺序调整：
统计每个单词出现的次数，并按次数降序排列
次数相同，按单词长度升序排列
次数和单词长度均相同，按字典升序排列
请输出处理后的字符串，每个单词以一个空格分隔。

输入描述
一行字符串，每个字符取值范围：[a-zA-z0-9] 以及空格，字符串长度范围：[1，1000]

输出描述
重新排序后的字符串，每个单词间隔1个空格，且首尾无空格

用例
输入	This is an apple
输出	an is This aelpp
说明	无
输入	My sister is in the house not in the yard
输出	in in eht eht My is not adry ehosu eirsst
说明	无
 */

import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;
import java.util.StringJoiner;

/**
  * 
  题目解析
本题需要注意的是，先进行单词内部调整，然后再进行单词间顺序。

考察的是自定义排序。

Python解法的第16行排序原理，请看：

Python3 - list sort方法实现多条件自定义排序_伏城之外的博客-CSDN博客
  */
public class 字符串重新排序 {
   
    public static void main(String[] args) {
        
        Scanner sc = new Scanner(System.in);
 
        String[] arr = sc.nextLine().split(" ");
        System.out.println(getResult(arr));
    }
 
    public static String getResult(String[] arr) {
        // 单词内部调整：对每个单词字母重新按字典序排序
        //arr = Arrays.stream(arr).map(s -> sortStr(s)).toArray(String[]::new);

        for(String str : arr){

            sortStr(str);

        }
 
        // 统计每个单词出现的次数
        HashMap<String, Integer> count = new HashMap<>();
        for (String s : arr) {
            count.put(s, count.getOrDefault(s, 0) + 1);
        }
 
        Arrays.sort(
                arr,
                (a, b) -> {
                    if (count.get(a) - count.get(b) != 0) {
                        return count.get(b) - count.get(a); // 按单词出现次数降序排列
                    } else if (a.length() != b.length()) {
                        return a.length() - b.length(); // 次数相同，按单词长度升序排列
                    } else {
                        return a.compareTo(b); // 次数和单词长度均相同，按字典升序排列
                    }
                });
 
        StringJoiner sj = new StringJoiner(" ");
        for (String s : arr) sj.add(s);
        return sj.toString();
    }
 
    // 对单词字母重新按字典序排序
    public static String sortStr(String word) {
        char[] cArr = word.toCharArray();
        Arrays.sort(cArr);
        return new String(cArr);
    }

}
